﻿namespace SharpF2.ModelView
{
	using System;
	using System.Collections.Generic;
	using System.IO;
	using System.Text;

	/// <summary>
	/// Define a file item
	/// </summary>
	public class FileItem : Item
	{
		#region Constructors

		/// <summary>
		/// Initializes a new instance of the <see cref="FileItem" /> class. 
		/// Default constructor.
		/// </summary>
		public FileItem()
		{
			InConflict = false;
			outputFileName = String.Empty;
			inputFilePath = String.Empty;
			OutputFilePath = String.Empty;
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="FileItem" /> class. 
		/// Constructor specifying an input file path.
		/// </summary>
		/// <param name="inputFilePath">The input file path.</param>
		public FileItem(string inputFilePath)
		{
			InConflict = false;
			InputFilePath = inputFilePath;
			outputFileName = String.Empty;
			OutputFilePath = String.Empty;
		}

		#endregion

		#region Private Attributes

		/// <summary>
		/// The index of the file.
		/// </summary>
		private int fileIndex;

		/// <summary>
		/// True if the file is in conflict with another file.
		/// </summary>
		private bool inConflict;

		/// <summary>
		/// The input FilePath.
		/// </summary>
		private string inputFilePath;

		/// <summary>
		/// The output (destination) file name.
		/// </summary>
		private string outputFileName;

		#endregion

		#region Public Properties

		/// <summary>
		/// Gets or sets FileIndex.
		/// </summary>
		public int FileIndex
		{
			get { return fileIndex; }

			set
			{
				fileIndex = value;
				NotifyPropertyChanged("FileIndex");
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether InConflict.
		/// </summary>
		public bool InConflict
		{
			get { return inConflict; }

			set
			{
				inConflict = value;
				NotifyPropertyChanged("InConflict");
			}
		}

		/// <summary>
		/// Gets the input directory path.
		/// </summary>
		public string InputDirectoryPath { get; private set; }

		/// <summary>
		/// Gets the input file name.
		/// </summary>
		public string InputFileName { get; private set; }

		/// <summary>
		/// Gets or sets the Input FilePath property, the setter update InputFilePath, 
		/// InputDirectoryPath, InputFileName and InputFileNameExtension.
		/// </summary>
		public string InputFilePath
		{
			get { return inputFilePath; }

			set
			{
				if (!File.Exists(value)) return;
				inputFilePath = value;
				InputDirectoryPath = Path.GetDirectoryName(value);
				InputFileName = Path.GetFileName(value);
				RegexText = InputFileName;
				NotifyPropertyChanged("InputFilePath");
				NotifyPropertyChanged("InputDirectoryPath");
				NotifyPropertyChanged("InputFileName");
				NotifyPropertyChanged("InputFileNameExtension");
			}
		}

		/// <summary>
		/// Gets or sets the input text resource.
		/// </summary>
		public TextItem InputTextItem { get; set; }

		/// <summary>
		/// Gets or sets the output file name, the setter update OutputFilePath.
		/// </summary>
		public string OutputFileName
		{
			get { return outputFileName; }

			set
			{
				outputFileName = value;

				if (null == value)
				{
					OutputFilePath = string.Empty;
					return;
				}

				UpdateOutputFileName();

				NotifyPropertyChanged("OutputFileName");
			}
		}

		/// <summary>
		/// Gets the output file path.
		/// </summary>
		public string OutputFilePath { get; private set; }

		#endregion

		#region Public Members

		/// <summary>
		/// Update the FileItem OutputFileName by an outPatternStrings.
		/// </summary>
		/// <param name="outPatternStrings">The outPatternStrings specifying the format of 
		/// the destination filename.</param>
		public void UpdateOutputFileName(IEnumerable<String> outPatternStrings)
		{
			var localOutputFileName = new StringBuilder(outputFileName.Length * 2);
			errorMessage = String.Empty;

			if (null == outPatternStrings)
			{
				errorMessage = "Internal error : outPatternStrings is null";
				return;
			}

			foreach (var identifier in outPatternStrings)
			{
				if (string.IsNullOrEmpty(identifier)) continue;

				switch (identifier[0])
				{
					case '$':
						{
							var identifierLength = identifier.Length - 3;
							if (identifierLength <= 0)
								break;
							var identifierId = identifier.Substring(2, identifierLength);
							if (IdentifiersValue.ContainsKey(identifierId))
								localOutputFileName.Append(IdentifiersValue[identifierId]);
							else if (null != InputTextItem &&
							         InputTextItem.IdentifiersValue.ContainsKey(identifierId))
								localOutputFileName.Append(InputTextItem.IdentifiersValue[identifierId]);
							break;
						}
					case '#':
						{
							var numberLength = identifier.Length;
							var number = FileIndex.ToString();
							if (numberLength - number.Length > 0)
							{
								var numberBase = new string('0', numberLength - number.Length);
								localOutputFileName.Append(numberBase + number);
							}
							else
								localOutputFileName.Append(number);
							break;
						}
					default:
						{
							localOutputFileName.Append(identifier);
							break;
						}
				}
			}

			outputFileName = localOutputFileName.ToString();
			UpdateOutputFileName();

			NotifyPropertyChanged("OutputFileName");
			NotifyPropertyChanged("ErrorMessage");
		}

		#endregion

		#region Private Members

		private void UpdateOutputFileName()
		{
			outputFileName = outputFileName.Replace("?", String.Empty)
				.Replace("\\", String.Empty)
				.Replace("//", String.Empty)
				.Replace("<", String.Empty)
				.Replace(">", String.Empty)
				.Replace("\"", String.Empty)
				.Replace("*", String.Empty)
				.Replace(":", String.Empty)
				.Replace("|", String.Empty);

			OutputFilePath = (InputDirectoryPath ?? String.Empty) +
			                 @"\" +
			                 outputFileName;
			OutputFilePath = OutputFilePath.Replace("\\\\", "\\");
		}

		#endregion
	}
}